package com.yuntsg.ruiijn.JiaXinZhi;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;

import java.sql.SQLException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * WOS论文，单位信息，基金信息，利用已经有的规则进行规范，并返回标准名称。
 * 贾新志 2023.07.14
 */

public class InfoGetRuleName {

    static String limit = "";
    //    static String limit = " limit 1";
    static int onePageNum = 1000;

    public static void main(String[] args) throws Exception {
//        getUnitAndFundRuleFile(); // 这个方法是生成规则文件用的，生成完成后就不需要了。

        // 服务器启动时，先把这个程序给加载上，即获取两个规则文件
        List<String> unitRuleFile = getRuleFile("C:\\unitRuleFile_2023_07_14.txt");
        List<String> fundRuleFile = getRuleFile("C:\\fundRuleFile_2023_07_14.txt");

        // 下面是使用时，直接调用规则文件，若有则返回标准名字，若无返回空字符串。
        String fund = "National Natural Science Foundation of China";
        System.out.println(getRuleName(fund, fundRuleFile));

        String univ = "Soochow University, Department Urol, Affiliated Hospital 2, 1055 Sanxiang Road, Suzhou 215000, People's Republic of China";
        System.out.println(getRuleName(univ, unitRuleFile));


// main
    }

    // 规则的主体文件，按字符串的长度，从长到短的顺序进行匹配。
    public static String getRuleName(String fund, List<String> fundRuleFile) {
        fund = fund.toLowerCase().trim();
        for (String s : fundRuleFile) {
            String[] split = s.split("_");
            if (split.length == 3) {
                String front = split[0];
                String end = split[1];
                String name = split[2];
                if (fund.contains(" " + front + " ") || fund.startsWith(front) || fund.endsWith(front)) {
                    if (end.length() > 1) {
                        if (fund.contains(" " + end + " ") || fund.startsWith(end) || fund.endsWith(end)) {
                            return name;
                        }
                    } else {
                        return name;
                    }
                }
            }
        }
        return "";
    }

    // 读取规则文件
    public static List<String> getRuleFile(String filePath) {
        List<String> rule = new ArrayList<>();
        List<String> list = FileUtil.readLines(filePath, "utf-8");
        for (String s : list) {
            String[] split = s.split("_");
            if (split.length == 3) {
                rule.add(s);
            }
        }
        return rule;
    }

    public static void getUnitAndFundRuleFile() throws SQLException {
        String ruleUnitTable = "rule.rule_unit_2302";
        Map<String, Integer> infoAndLenMap = readTable(ruleUnitTable, "", "id", "info`,`type`,`branch`,`hospital");
        System.out.println("infoAndLenMap.size():1 " + infoAndLenMap.size());
        List<String> list = FileUtil.readLines("C:\\Users\\Administrator\\Desktop\\临时文件\\bao.txt", "utf-8");
        for (String s : list) {
            String[] split = s.split("_");
            // Linzhou Cent Hosp_Henan_林州市中医院
            if (split.length == 3 && !isContainChinese(split[0]) && !isContainChinese(split[1])) {
                String str = split[0].trim() + "_" + split[1].trim() + "_中国-" + split[2].trim();
                if (str.contains(" ")) {
                    infoAndLenMap.put(str.toLowerCase(), (split[0].trim() + "_" + split[1].trim()).length());
                }
            }
        }
        System.out.println("infoAndLenMap.size():2 " + infoAndLenMap.size());
        Map<String, Integer> unitRuleMap = mapSortValueStrInt(infoAndLenMap);
        for (Map.Entry<String, Integer> entry : unitRuleMap.entrySet()) {
            FileUtil.appendUtf8String(entry.getKey() + System.lineSeparator(), "C:\\unitRuleFile_2023_07_14.txt");
        }

        Map<String, Integer> fundInfoAndLenMap = readFundTable(ruleUnitTable, "", "id", "info`,`type`,`standard");
        Map<String, Integer> fundRuleMap = mapSortValueStrInt(fundInfoAndLenMap);
        for (Map.Entry<String, Integer> entry : fundRuleMap.entrySet()) {
            FileUtil.appendUtf8String(entry.getKey() + System.lineSeparator(), "C:\\fundRuleFile_2023_07_14.txt");
        }


    }

    public static Map<String, Integer> readFundTable(String tableName, String limit, String autoId, String field) throws SQLException {
        int onePageNum = 1000;
        Map<String, Integer> fundInfoAndLenMap = new HashMap<>();
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + tableName);
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + tableName).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            for (Integer startId : tableList) {
                try {
                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + tableName + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1) + limit);
                    for (Entity entry : tableData) {
                        String info = getStrField(entry, "info");
                        String type = getStrField(entry, "type");
                        String standard = getStrField(entry, "standard");
                        if (type.equals("fund") && info.length() > 2 && !isContainChinese(info) && standard.length() > 3) {
                            String str = info + "__" + standard;
                            if (str.contains(" ")) {
                                fundInfoAndLenMap.put(str.toLowerCase(), info.length());
                            }
                        }
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return fundInfoAndLenMap;
    }

    public static Map<String, Integer> readTable(String tableName, String limit, String autoId, String field) throws SQLException {
        int onePageNum = 1000;
        Map<String, Integer> infoAndLenMap = new HashMap<>();
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + tableName);
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + tableName).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            for (Integer startId : tableList) {
                try {
                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + tableName + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1) + limit);
                    for (Entity entry : tableData) {
                        String info = getStrField(entry, "info");
                        String type = getStrField(entry, "type");
                        String branch = getStrField(entry, "branch");
                        String hospital = getStrField(entry, "hospital");
                        String unit = hospital.length() > 3 ? hospital : branch;
                        if (type.equals("unit") && info.length() > 3 && !isContainChinese(info) && unit.length() > 3) {
                            String str = info + "__" + unit;
                            if (str.contains(" ")) {
                                infoAndLenMap.put(str.toLowerCase(), info.length());
                            }
                        }
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return infoAndLenMap;
    }

    // 对Map进行排序，此排序为最大的在前面，输入一个map，再返回一个排序后的新map，String, Integer类型。
    public static Map<String, Integer> mapSortValueStrInt(Map<String, Integer> mapName) {
        Map<String, Integer> result = new LinkedHashMap<>();
        mapName.entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue()
                        .reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    public static String getStrField(Entity entry, String field) {
        if (null != entry) {
            String str = entry.getStr(field);
            if (null != str && str.length() > 0 && !str.toLowerCase().trim().equals("null")) {
                return str.trim();
            }
        }
        return "";
    }

    public static boolean isContainChinese(String str) {
        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(str);
        return m.find();
    }


// end
}
